home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_200 / 247_03 / williams.c < prev    next >
Text File  |  1989-04-17  |  6KB  |  178 lines

  1. /*
  2.  *   Program to factor big numbers using Williams (p+1) method.
  3.  *   Works when for some prime divisor p of n, p+1 has only
  4.  *   small factors.
  5.  *   See "Speeding the Pollard and Elliptic Curve Methods"
  6.  *   by Peter Montgomery, Math. Comp. Vol. 48. Jan. 1987 pp243-264
  7.  */
  8.  
  9. #include <stdio.h>
  10. #include "miracl.h"
  11.  
  12. #define LIMIT1 4000       /* must be int, and > MULT/2 */
  13. #define LIMIT2 200000L    /* may be long */
  14. #define MULT   2310       /* must be int, product of small primes 2.3.. */
  15. #define NTRYS  3          /* number of attempts */
  16. big t,t2;
  17.  
  18. void lucas(p,r,n,vp,v)
  19. big p,v,n,vp;
  20. int r;
  21. { /* calculate r-th elements of lucas sequence mod n */
  22.     int k,rr;
  23.     convert(2,vp);
  24.     copy(p,v);
  25.     subtract(n,p,p);
  26.     k=1;
  27.     rr=r;
  28.     while ((rr/=2)>1) k*=2;
  29.     while (k>0)
  30.     { /* use binary method */
  31.         mad(v,vp,p,n,n,vp);
  32.         mad(v,v,t2,n,n,v);
  33.         if ((r&k)>0)
  34.         {
  35.             mad(p,v,vp,n,n,t);
  36.             copy(v,vp);
  37.             negate(t,v);
  38.         }
  39.         k/=2;
  40.     }
  41.     subtract(n,p,p);
  42. }
  43.  
  44. main()
  45. {  /*  factoring program using Williams (p+1) method */
  46.     int k,phase,m,nt,iv,pos,btch;
  47.     int *primes;
  48.     long i,p,pa;
  49.     big b,q,n,fp,fvw,fd,fn;
  50.     static big fu[1+MULT/2];
  51.     static bool cp[1+MULT/2];
  52.     mirsys(50,MAXBASE);
  53.     b=mirvar(0);
  54.     t2=mirvar((-2));
  55.     q=mirvar(0);
  56.     n=mirvar(0);
  57.     t=mirvar(0);
  58.     fp=mirvar(0);
  59.     fvw=mirvar(0);
  60.     fd=mirvar(0);
  61.     fn=mirvar(0);
  62.     primes=gprime(LIMIT1);
  63.     for (m=1;m<=MULT/2;m+=2)
  64.         if (igcd(MULT,m)==1)
  65.         {
  66.             fu[m]=mirvar(0);
  67.             cp[m]=TRUE;
  68.         }
  69.         else cp[m]=FALSE;
  70.     printf("input number to be factored\n");
  71.     cinnum(n,stdin);
  72.     if (prime(n))
  73.     {
  74.         printf("this number is prime!\n");
  75.         exit(0);
  76.     }
  77.     for (nt=0,k=3;k<10;k++)
  78.     { /* try more than once for p+1 condition (may be p-1) */
  79.         convert(k,b);              /* try b=3,4,5..        */
  80.         convert((k*k-4),t);
  81.         if (gcd(t,n,t)!=1) continue; /* check (b*b-4,n)!=0 */
  82.         nt++;
  83.         phase=1;
  84.         p=0;
  85.         btch=50;
  86.         i=0;
  87.         printf("phase 1 - trying all primes less than %d\n",LIMIT1);
  88.         printf("prime= %8ld",p);
  89.         forever
  90.         { /* main loop */
  91.             if (phase==1)
  92.             { /* looking for all factors of p+1 < LIMIT1 */
  93.                 p=primes[i];
  94.                 if (primes[i+1]==0)
  95.                 { /* now change gear */
  96.                     phase=2;
  97.                     printf("\nphase 2 - trying last prime less than %ld\n"
  98.                            ,LIMIT2);
  99.                     printf("prime= %8ld",p);
  100.                     copy(b,fu[1]);
  101.                     copy(b,fp);
  102.                     mad(b,b,t2,n,n,fd);
  103.                     negate(b,t);
  104.                     mad(fd,b,t,n,n,fn);
  105.                     for (m=5;m<=MULT/2;m+=2)
  106.                     { /* store fu[m] = Vm(b) */
  107.                         negate(fp,t);
  108.                         mad(fn,fd,t,n,n,t);
  109.                         copy(fn,fp);
  110.                         copy(t,fn);
  111.                         if (!cp[m]) continue;
  112.                         copy(t,fu[m]);
  113.                     }
  114.                     lucas(b,MULT,n,fp,fd);
  115.                     iv=p/MULT;
  116.                     if (p%MULT>MULT/2) iv++,p=2*(long)iv*MULT-p;
  117.                     lucas(fd,iv,n,fp,fvw);
  118.                     negate(fp,fp);
  119.                     subtract(fvw,fu[p%MULT],q);
  120.                     btch*=10;
  121.                     i++;
  122.                     continue;
  123.                 }
  124.                 pa=p;
  125.                 while ((LIMIT1/p) > pa) pa*=p;
  126.                 lucas(b,(int)pa,n,fp,q);
  127.                 copy(q,b);
  128.                 decr(q,2,q);
  129.             }
  130.             else
  131.             { /* phase 2 - looking for last large prime factor of (p+1) */
  132.                 p+=2;
  133.                 pos=p%MULT;
  134.                 if (pos>MULT/2)
  135.                 { /* increment giant step */
  136.                     iv++;
  137.                     p=(long)iv*MULT+1;
  138.                     pos=1;
  139.                     copy(fvw,t);
  140.                     mad(fvw,fd,fp,n,n,fvw);
  141.                     negate(t,fp);
  142.                 }
  143.                 if (!cp[pos]) continue;
  144.                 subtract(fvw,fu[pos],t);
  145.                 mad(q,t,t,n,n,q);  /* batching gcds */
  146.             }
  147.             if (i++%btch==0)
  148.             { /* try for a solution */
  149.                 printf("\b\b\b\b\b\b\b\b%8ld",p);
  150.                 gcd(q,n,t);
  151.                 if (size(t)==1)
  152.                 {
  153.                     if (p>LIMIT2) break;
  154.                     else continue;
  155.                 }
  156.                 if (compare(t,n)==0)
  157.                 {
  158.                     printf("\ndegenerate case");
  159.                     break;
  160.                 }
  161.                 printf("\nfactors are\n");
  162.                 if (prime(t)) printf("prime factor     ");
  163.                 else          printf("composite factor ");
  164.                 cotnum(t,stdout);
  165.                 divide(n,t,n);
  166.                 if (prime(n)) printf("prime factor     ");
  167.                 else          printf("composite factor ");
  168.                 cotnum(n,stdout);
  169.                 exit(0);
  170.             }
  171.         } 
  172.         if (nt>=NTRYS) break;
  173.         printf("\ntrying again\n");
  174.     }
  175.     printf("\nfailed to factor\n");
  176. }
  177.  
  178.